home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / comm / term / term_source.lha / Extras / Source / term-source.lha / ARexx.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  16KB  |  904 lines

  1. /*
  2. **    ARexx.c
  3. **
  4. **    ARexx interface general support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* IsNumeric(STRPTR String):
  17.      *
  18.      *    Is the string really a number?
  19.      */
  20.  
  21. BOOL
  22. IsNumeric(STRPTR String)
  23. {
  24.     while(*String == ' ' || *String == '\t')
  25.         String++;
  26.  
  27.     while(*String)
  28.     {
  29.         if(*String < '0' || *String > '9')
  30.             return(FALSE);
  31.         else
  32.             String++;
  33.     }
  34.  
  35.     return(TRUE);
  36. }
  37.  
  38.     /* CreateResult(STRPTR ResultString,LONG *Results):
  39.      *
  40.      *    Create a proper Rexx result string.
  41.      */
  42.  
  43. STRPTR
  44. CreateResult(STRPTR ResultString,LONG *Results)
  45. {
  46.     STRPTR Result;
  47.  
  48.     if(!(Result = CreateArgstring(ResultString,strlen(ResultString))))
  49.     {
  50.         Results[0] = RC_ERROR;
  51.         Results[1] = ERROR_NO_FREE_STORE;
  52.     }
  53.  
  54.     return(Result);
  55. }
  56.  
  57.     /* CreateResultLen(STRPTR ResultString,LONG *Results):
  58.      *
  59.      *    Create a proper Rexx result string given the
  60.      *    length of the source string.
  61.      */
  62.  
  63. STRPTR
  64. CreateResultLen(STRPTR ResultString,LONG *Results,LONG Len)
  65. {
  66.     STRPTR Result;
  67.  
  68.     if(!(Result = CreateArgstring(ResultString,Len)))
  69.     {
  70.         Results[0] = RC_ERROR;
  71.         Results[1] = ERROR_NO_FREE_STORE;
  72.     }
  73.  
  74.     return(Result);
  75. }
  76.  
  77.     /* CreateVarArgs(STRPTR Value,struct RexxPkt *Packet,STRPTR Stem,...):
  78.      *
  79.      *    Set a Rexx variable, special treatment.
  80.      */
  81.  
  82. BOOL
  83. CreateVarArgs(STRPTR Value,struct RexxPkt *Packet,STRPTR Stem,...)
  84. {
  85.     UBYTE Name[256];
  86.     va_list VarArgs;
  87.     LONG Result;
  88.  
  89.     va_start(VarArgs,Stem);
  90.     LimitedVSPrintf(sizeof(Name),Name,Stem,VarArgs);
  91.     va_end(VarArgs);
  92.  
  93.     if(Result = SetRexxVar((struct Message *)Packet->RexxMsg,Name,Value,strlen(Value)))
  94.     {
  95.         Packet->Results[0] = RC_ERROR;
  96.         Packet->Results[1] = Result;
  97.  
  98.         return(FALSE);
  99.     }
  100.     else
  101.         return(TRUE);
  102. }
  103.  
  104.     /* CreateVar(STRPTR Value,struct RexxPkt *Packet,STRPTR Name):
  105.      *
  106.      *    Set a Rexx variable, simple version.
  107.      */
  108.  
  109. STRPTR
  110. CreateVar(STRPTR Value,struct RexxPkt *Packet,STRPTR Name)
  111. {
  112.     LONG Result;
  113.  
  114.     if(Result = SetRexxVar((struct Message *)Packet->RexxMsg,Name,Value,strlen(Value)))
  115.     {
  116.         Packet->Results[0] = RC_ERROR;
  117.         Packet->Results[1] = Result;
  118.     }
  119.  
  120.     return(NULL);
  121. }
  122.  
  123.     /* CreateMatchBuffer(STRPTR Pattern):
  124.      *
  125.      *    Create a pattern buffer suitable for pattern matching.
  126.      */
  127.  
  128. STRPTR
  129. CreateMatchBuffer(STRPTR Pattern)
  130. {
  131.     STRPTR Buffer;
  132.     LONG Len;
  133.  
  134.     Len = strlen(Pattern) + 1;
  135.  
  136.     if(Buffer = (STRPTR)AllocVecPooled(2 * Len,MEMF_ANY))
  137.     {
  138.         if(ParsePatternNoCase(Pattern,Buffer,2 * Len) != -1)
  139.             return(Buffer);
  140.         else
  141.             FreeVecPooled(Buffer);
  142.     }
  143.  
  144.     return(NULL);
  145. }
  146.  
  147.     /* MatchBuffer(STRPTR Buffer,STRPTR Name):
  148.      *
  149.      *    Match a pattern against a string.
  150.      */
  151.  
  152. BOOL
  153. MatchBuffer(STRPTR Buffer,STRPTR Name)
  154. {
  155.     return((BOOL)(MatchPatternNoCase(Buffer,Name) != FALSE));
  156. }
  157.  
  158.     /* DeleteMatchBuffer(STRPTR Buffer):
  159.      *
  160.      *    Free a pattern matching buffer.
  161.      */
  162.  
  163. VOID
  164. DeleteMatchBuffer(STRPTR Buffer)
  165. {
  166.     FreeVecPooled(Buffer);
  167. }
  168.  
  169.     /* ToMode(STRPTR Name):
  170.      *
  171.      *    Turn a transfer mode name into a key.
  172.      */
  173.  
  174. LONG
  175. ToMode(STRPTR Name)
  176. {
  177.     STATIC STRPTR TransferModes[] =
  178.     {
  179.         "BINARY",
  180.         "TEXT",
  181.         "ASCII",
  182.         NULL
  183.     };
  184.  
  185.     LONG i;
  186.  
  187.     for(i = 0 ; TransferModes[i] ; i++)
  188.     {
  189.         if(!Stricmp(Name,TransferModes[i]))
  190.             return(i);
  191.     }
  192.  
  193.     return(-1);
  194. }
  195.  
  196.     /* ToList(STRPTR Name):
  197.      *
  198.      *    Turn a list name into a key.
  199.      */
  200.  
  201. LONG
  202. ToList(STRPTR Name)
  203. {
  204.     STATIC STRPTR ListTypes[GLIST_COUNT] =
  205.     {
  206.         "UPLOAD",
  207.         "DOWNLOAD",
  208.         "DIAL",
  209.         "WAIT",
  210.         "TRAP"
  211.     };
  212.  
  213.     LONG i;
  214.  
  215.     for(i = 0 ; i < GLIST_COUNT ; i++)
  216.     {
  217.         if(!Stricmp(Name,ListTypes[i]))
  218.             return(i);
  219.     }
  220.  
  221.     return(-1);
  222. }
  223.  
  224.     /* ToConfig(STRPTR Name):
  225.      *
  226.      *    Turn a configuration name into a key.
  227.      */
  228.  
  229. LONG
  230. ToConfig(STRPTR Name)
  231. {
  232.     STATIC STRPTR DataTypes[DATATYPE_COUNT] =
  233.     {
  234.         "TRANSLATIONS",
  235.         "FUNCTIONKEYS",
  236.         "CURSORKEYS",
  237.         "FASTMACROS",
  238.         "HOTKEYS",
  239.         "SPEECH",
  240.         "SOUND",
  241.         "BUFFER",
  242.         "CONFIGURATION",
  243.         "PHONE",
  244.         "SCREENTEXT",
  245.         "SCREENIMAGE"
  246.     };
  247.  
  248.     LONG i;
  249.  
  250.     for(i = 0 ; i < DATATYPE_COUNT ; i++)
  251.     {
  252.         if(!Stricmp(Name,DataTypes[i]))
  253.             return(i);
  254.     }
  255.  
  256.     return(-1);
  257. }
  258.  
  259.     /* ToRequester(STRPTR Name):
  260.      *
  261.      *    Turn a requester name into a key.
  262.      */
  263.  
  264. LONG
  265. ToRequester(STRPTR Name)
  266. {
  267.     STRPTR RequesterTypes[REQUESTER_COUNT] =
  268.     {
  269.         "SERIAL",
  270.         "MODEM",
  271.         "SCREEN",
  272.         "TERMINAL",
  273.         "EMULATION",
  274.         "CLIPBOARD",
  275.         "CAPTURE",
  276.         "COMMANDS",
  277.         "MISC",
  278.         "PATH",
  279.         "TRANSFER",
  280.         "TRANSLATIONS",
  281.         "FUNCTIONKEYS",
  282.         "CURSORKEYS",
  283.         "FASTMACROS",
  284.         "HOTKEYS",
  285.         "SPEECH",
  286.         "SOUND",
  287.         "PHONE"
  288.     };
  289.  
  290.     LONG i;
  291.  
  292.     for(i = 0 ; i < REQUESTER_COUNT ; i++)
  293.     {
  294.         if(!Stricmp(Name,RequesterTypes[i]))
  295.             return(i);
  296.     }
  297.  
  298.     return(-1);
  299. }
  300.  
  301.     /* ToWindow(STRPTR Name):
  302.      *
  303.      *    Turn a window name into a key.
  304.      */
  305.  
  306. LONG
  307. ToWindow(STRPTR Name)
  308. {
  309.     STATIC STRPTR WindowTypes[WINDOWID_COUNT] =
  310.     {
  311.         "BUFFER",
  312.         "REVIEW",
  313.         "PACKET",
  314.         "FASTMACROS",
  315.         "STATUS",
  316.         "MAIN",
  317.         "UPLOADQUEUE",
  318.         "SINGLECHARENTRY"
  319.     };
  320.  
  321.     LONG i;
  322.  
  323.     for(i = 0 ; i < WINDOWID_COUNT ; i++)
  324.     {
  325.         if(!Stricmp(WindowTypes[i],Name))
  326.             return(i);
  327.     }
  328.  
  329.     return(-1);
  330. }
  331.  
  332.     /* ReplyRexxCommand():
  333.      *
  334.      *    Reply a command request the rexx server - or someone else -
  335.      *    has passed to us.
  336.      */
  337.  
  338. STATIC VOID
  339. ReplyRexxCommand(struct RexxMsg *RexxMessage,LONG Primary,LONG Secondary)
  340. {
  341.     if(RexxMessage)
  342.     {
  343.         RexxMessage->rm_Result1 = Primary;
  344.         RexxMessage->rm_Result2 = Secondary;
  345.  
  346.         ReplyMsg((struct Message *)RexxMessage);
  347.     }
  348. }
  349.  
  350.     /* InvokeRexxCommand(struct RexxPkt *Packet):
  351.      *
  352.      *    Invoke an ARexx command.
  353.      */
  354.  
  355. STATIC BOOL
  356. InvokeRexxCommand(struct RexxPkt *Packet)
  357. {
  358.         /* Asynchronous command? */
  359.  
  360.     if(Packet->CommandInfo->Async)
  361.     {
  362.             /* Execute the command on the schedule of the rexx server process. */
  363.  
  364.         STRPTR Result = (*Packet->CommandInfo->Routine)(Packet);
  365.  
  366.             /* Will the command clean up all by itself? */
  367.  
  368.         if(!Packet->CommandInfo->AutoCleanup)
  369.             RexxPktCleanup(Packet,Result);
  370.     }
  371.     else
  372.     {
  373.         struct RexxPkt *NewPacket;
  374.  
  375.             /* Create message packet. */
  376.  
  377.         if(NewPacket = (struct RexxPkt *)AllocVecPooled(sizeof(struct RexxPkt),MEMF_ANY))
  378.         {
  379.                 /* Set up message packet. */
  380.  
  381.             CopyMem(Packet,NewPacket,sizeof(struct RexxPkt));
  382.  
  383.             NewPacket->Message.mn_ReplyPort    = RexxPort;
  384.             NewPacket->Message.mn_Length    = sizeof(struct RexxPkt);
  385.  
  386.                 /* Post it. */
  387.  
  388.             PutMsg(TermRexxPort,(struct Message *)NewPacket);
  389.         }
  390.         else
  391.             ReplyRexxCommand(Packet->RexxMsg,-1,0);
  392.     }
  393.  
  394.     return(TRUE);
  395. }
  396.  
  397.     /* ParseRexxCommand(struct RexxMsg *RexxMsg):
  398.      *
  399.      *    Handles the synchronous Rexx commands and returns the
  400.      *    message if no matching command is found.
  401.      */
  402.  
  403. STATIC BOOL
  404. ParseRexxCommand(struct RexxMsg *RexxMsg)
  405. {
  406.     UBYTE CommandBuffer[MAX_FILENAME_LENGTH];
  407.     STRPTR Command,CommandArgs;
  408.     LONG Len;
  409.  
  410.         /* Clear the local variables. */
  411.  
  412.     CommandBuffer[0]    = 0;
  413.     Command                = RexxMsg->rm_Args[0];
  414.     CommandArgs            = NULL;
  415.     Len                    = 0;
  416.  
  417.         /* Skip leading blank spaces. */
  418.  
  419.     while(*Command == ' ' || *Command == '\t')
  420.         Command++;
  421.  
  422.         /* Extract the command name. */
  423.  
  424.     do
  425.     {
  426.             /* Found the end of the string? */
  427.  
  428.         if(!Command[Len])
  429.         {
  430.                 /* Copy the command name. */
  431.  
  432.             LimitedStrcpy(sizeof(CommandBuffer),CommandBuffer,Command);
  433.  
  434.                 /* No arguments are provided. */
  435.  
  436.             CommandArgs = NULL;
  437.  
  438.             break;
  439.         }
  440.  
  441.             /* Found a blank space? */
  442.  
  443.         if(Command[Len] == ' ' || Command[Len] == '\t')
  444.         {
  445.                 /* Copy the command name. */
  446.  
  447.             CopyMem(Command,CommandBuffer,Len);
  448.  
  449.             CommandBuffer[Len] = 0;
  450.  
  451.                 /* Look for any arguments. */
  452.  
  453.             CommandArgs = &Command[Len + 1];
  454.  
  455.                 /* Skip blank spaces. */
  456.  
  457.             while(*CommandArgs == ' ' || *CommandArgs == '\t')
  458.                 CommandArgs++;
  459.  
  460.             break;
  461.         }
  462.     }
  463.     while(++Len < 30);
  464.  
  465.         /* Did we find a command name? */
  466.  
  467.     if(CommandBuffer[0])
  468.     {
  469.         struct CommandInfo *CommandInfo;
  470.         LONG CommandIndex;
  471.  
  472.             /* Which command is it? */
  473.  
  474.         for(CommandIndex = 0, CommandInfo = NULL ; CommandIndex < CommandTableSize ; CommandIndex++)
  475.         {
  476.             if(!Stricmp(CommandBuffer,CommandTable[CommandIndex].Name))
  477.             {
  478.                 CommandInfo = &CommandTable[CommandIndex];
  479.  
  480.                 break;
  481.             }
  482.         }
  483.  
  484.             /* Did we find the command? */
  485.  
  486.         if(CommandInfo)
  487.         {
  488.             struct RexxPkt Packet;
  489.             BOOL Processed;
  490.  
  491.             Processed = FALSE;
  492.  
  493.                 /* Set the result codes to defaults. */
  494.  
  495.             Packet.Results[0]    = RC_OK;
  496.             Packet.Results[1]    = 0;
  497.  
  498.                 /* Fill in the rest. */
  499.  
  500.             Packet.CommandInfo    = CommandInfo;
  501.             Packet.RexxMsg        = RexxMsg;
  502.  
  503.                 /* Does this command accept any arguments? */
  504.  
  505.             if(CommandInfo->Arguments)
  506.             {
  507.                 LONG *Array;
  508.  
  509.                     /* Determine length of argument string. */
  510.  
  511.                 if(CommandArgs)
  512.                     Len = strlen(CommandArgs);
  513.                 else
  514.                     Len = 0;
  515.  
  516.                     /* Allocate temporary buffer, we will need to
  517.                      * attach a line-feed character to the argument
  518.                      * string.
  519.                      */
  520.  
  521.                 if(Array = (LONG *)AllocVecPooled(12 * sizeof(LONG) + Len + 2,MEMF_ANY | MEMF_CLEAR))
  522.                 {
  523.                     struct RDArgs *Args;
  524.                     STRPTR Buffer;
  525.  
  526.                         /* Get the argument buffer. */
  527.  
  528.                     Buffer = (STRPTR)&Array[12];
  529.  
  530.                         /* Copy the argument string. */
  531.  
  532.                     if(CommandArgs && Len)
  533.                         CopyMem(CommandArgs,Buffer,Len);
  534.  
  535.                         /* Attach the line-feed character. */
  536.  
  537.                     Buffer[Len] = '\n';
  538.  
  539.                         /* Allocate argument parser data. */
  540.  
  541.                     if(Args = (struct RDArgs *)AllocDosObjectTags(DOS_RDARGS,TAG_DONE))
  542.                     {
  543.                         Packet.Array    = (STRPTR *)Array;
  544.                         Packet.Args        = Args;
  545.  
  546.                             /* Don't prompt for input! */
  547.  
  548.                         Args->RDA_Flags |= RDAF_NOPROMPT;
  549.  
  550.                             /* Set up parser data. */
  551.  
  552.                         Args->RDA_Source.CS_Buffer    = Buffer;
  553.                         Args->RDA_Source.CS_Length    = Len + 1;
  554.                         Args->RDA_Source.CS_CurChr    = 0;
  555.  
  556.                             /* Parse the arguments. */
  557.  
  558.                         if(ReadArgs(CommandInfo->Arguments,Array,Args))
  559.                         {
  560.                             BOOL ArgsRequired;
  561.                             UWORD Inclusion;
  562.                             LONG i,Counted;
  563.  
  564.                             Inclusion        = InclusionTable[CommandIndex];
  565.                             ArgsRequired    = FALSE;
  566.  
  567.                                 /* Look for required arguments. */
  568.  
  569.                             for(i = Counted = 0 ; i < 12 ; i++)
  570.                             {
  571.                                 if(Inclusion & (1L << i))
  572.                                 {
  573.                                     ArgsRequired = TRUE;
  574.  
  575.                                     if(Array[i])
  576.                                         Counted++;
  577.                                 }
  578.                             }
  579.  
  580.                                 /* Are any arguments required
  581.                                  * but not provided?
  582.                                  */
  583.  
  584.                             if(ArgsRequired && !Counted)
  585.                             {
  586.                                 Packet.Results[0] = RC_ERROR;
  587.                                 Packet.Results[1] = ERROR_REQUIRED_ARG_MISSING;
  588.                             }
  589.                             else
  590.                             {
  591.                                 struct ExclusionInfo *Exclusion = ExclusionTable[CommandIndex];
  592.  
  593.                                     /* Any mutually-exclusive arguments? */
  594.  
  595.                                 if(Exclusion)
  596.                                 {
  597.                                     BOOL ArgsOkay = TRUE;
  598.  
  599.                                     i = 0;
  600.  
  601.                                         /* Look for arguments to
  602.                                          * exclude each other.
  603.                                          */
  604.  
  605.                                     while(ArgsOkay && Exclusion[i].A != -1)
  606.                                     {
  607.                                         if(Array[Exclusion[i].A] && Array[Exclusion[i].B])
  608.                                             ArgsOkay = FALSE;
  609.                                         else
  610.                                             i++;
  611.                                     }
  612.  
  613.                                         /* All arguments correct? */
  614.  
  615.                                     if(ArgsOkay)
  616.                                         Processed = InvokeRexxCommand(&Packet);
  617.                                     else
  618.                                     {
  619.                                         Packet.Results[0] = RC_ERROR;
  620.                                         Packet.Results[1] = ERROR_TOO_MANY_ARGS;
  621.                                     }
  622.                                 }
  623.                                 else
  624.                                     Processed = InvokeRexxCommand(&Packet);
  625.                             }
  626.  
  627.                                 /* Free allocated parser data. */
  628.  
  629.                             if(!Processed)
  630.                                 FreeArgs(Args);
  631.                         }
  632.                         else
  633.                         {
  634.                             LONG Error = IoErr();
  635.  
  636.                             SetIoErr(Error);
  637.  
  638.                             Packet.Results[0] = RC_ERROR;
  639.                             Packet.Results[1] = IoErr();
  640.                         }
  641.  
  642.                             /* Free parser data. */
  643.  
  644.                         if(!Processed)
  645.                             FreeDosObject(DOS_RDARGS,Args);
  646.                     }
  647.                     else
  648.                     {
  649.                         Packet.Results[0] = RC_ERROR;
  650.                         Packet.Results[1] = ERROR_NO_FREE_STORE;
  651.                     }
  652.  
  653.                         /* Free temporary buffer. */
  654.  
  655.                     if(!Processed)
  656.                         FreeVecPooled(Array);
  657.                 }
  658.                 else
  659.                 {
  660.                     Packet.Results[0] = RC_ERROR;
  661.                     Packet.Results[1] = ERROR_NO_FREE_STORE;
  662.                 }
  663.             }
  664.             else
  665.             {
  666.                 Packet.Array    = NULL;
  667.                 Packet.Args        = NULL;
  668.  
  669.                 Processed = InvokeRexxCommand(&Packet);
  670.             }
  671.  
  672.             if(!Processed)
  673.             {
  674.                 if(Packet.Results[0] && Packet.Results[1])
  675.                     LastRexxError = Packet.Results[1];
  676.  
  677.                 ReplyRexxCommand(RexxMsg,Packet.Results[0],Packet.Results[1]);
  678.             }
  679.  
  680.             return(TRUE);
  681.         }
  682.     }
  683.  
  684.     return(FALSE);
  685. }
  686.  
  687.     /* RexxPktCleanup(struct RexxPkt *Packet,STRPTR Result):
  688.      *
  689.      *    Free the memory allocated for a message packet.
  690.      */
  691.  
  692. VOID
  693. RexxPktCleanup(struct RexxPkt *Packet,STRPTR Result)
  694. {
  695.     if(Packet->Args)
  696.     {
  697.         FreeArgs(Packet->Args);
  698.  
  699.         FreeDosObject(DOS_RDARGS,Packet->Args);
  700.     }
  701.  
  702.     FreeVecPooled(Packet->Array);
  703.  
  704.     if(Packet->Results[0])
  705.     {
  706.             /* Store error code. */
  707.  
  708.         if(Packet->Results[1])
  709.         {
  710.             UBYTE Buffer[10];
  711.  
  712.             LimitedSPrintf(sizeof(Buffer),Buffer,"%ld",LastRexxError = Packet->Results[1]);
  713.  
  714.             if(Packet->RexxMsg)
  715.                 SetRexxVar((struct Message *)Packet->RexxMsg,"TERM.LASTERROR",Buffer,strlen(Buffer));
  716.         }
  717.  
  718.         ReplyRexxCommand(Packet->RexxMsg,Packet->Results[0],Packet->Results[1]);
  719.  
  720.         if(Result)
  721.             DeleteArgstring(Result);
  722.     }
  723.     else
  724.     {
  725.         if(Result)
  726.         {
  727.             if(Packet->RexxMsg)
  728.             {
  729.                 if(Packet->RexxMsg->rm_Action & RXFF_RESULT)
  730.                     ReplyRexxCommand(Packet->RexxMsg,0,(LONG)Result);
  731.                 else
  732.                 {
  733.                     DeleteArgstring(Result);
  734.  
  735.                     ReplyRexxCommand(Packet->RexxMsg,0,0);
  736.                 }
  737.             }
  738.             else
  739.                 DeleteArgstring(Result);
  740.         }
  741.         else
  742.             ReplyRexxCommand(Packet->RexxMsg,0,0);
  743.     }
  744. }
  745.  
  746.     /* RexxServer(VOID):
  747.      *
  748.      *    Asynchronous ARexx host server.
  749.      */
  750.  
  751. VOID SAVE_DS
  752. RexxServer(VOID)
  753. {
  754.         /* Create the public host port. */
  755.  
  756.     if(RexxPort = CreateMsgPort())
  757.     {
  758.         struct RexxMsg *RexxMsg;
  759.         BOOL Done = FALSE;
  760.         ULONG SignalSet;
  761.  
  762.         RexxPort->mp_Node.ln_Name    = RexxPortName;
  763.         RexxPort->mp_Node.ln_Pri    = 1;
  764.  
  765.             /* Make it a public port. */
  766.  
  767.         AddPort(RexxPort);
  768.  
  769.             /* Signal our father that we're running. */
  770.  
  771.         Signal((struct Task *)ThisProcess,SIG_HANDSHAKE);
  772.  
  773.             /* Go into loop and wait for input. */
  774.  
  775.         do
  776.         {
  777.             SignalSet = Wait(SIG_KILL | PORTMASK(RexxPort));
  778.  
  779.                 /* Are we to quit? */
  780.  
  781.             if(SignalSet & SIG_KILL)
  782.                 Done = TRUE;
  783.  
  784.                 /* This is probably a Rexx command. */
  785.  
  786.             if(SignalSet & PORTMASK(RexxPort))
  787.             {
  788.                     /* Pick up all the messages. */
  789.  
  790.                 while(RexxMsg = (struct RexxMsg *)GetMsg(RexxPort))
  791.                 {
  792.                         /* This is probably the reply to some
  793.                          * synchronous function invocation.
  794.                          */
  795.  
  796.                     if(RexxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
  797.                         FreeVecPooled(RexxMsg);
  798.                     else
  799.                     {
  800.                             /* At first try to run the
  801.                              * command asynchronously.
  802.                              * If this turns out to be
  803.                              * somewhat `impossible' pass
  804.                              * it to the `term' main process
  805.                              * or - if in batch mode - try
  806.                              * to deal with the message
  807.                              * on our own.
  808.                              */
  809.  
  810.                         if(!ParseRexxCommand(RexxMsg))
  811.                         {
  812.                             UBYTE Buffer[10];
  813.  
  814.                             LimitedSPrintf(sizeof(Buffer),Buffer,"%ld",LastRexxError = TERMERROR_UNKNOWN_COMMAND);
  815.  
  816.                             SetRexxVar((struct Message *)RexxMsg,"TERM.LASTERROR",Buffer,strlen(Buffer));
  817.  
  818.                             ReplyRexxCommand(RexxMsg,RC_ERROR,TERMERROR_UNKNOWN_COMMAND);
  819.                         }
  820.                     }
  821.                 }
  822.             }
  823.         }
  824.         while(!Done);
  825.  
  826.             /* Process remaining messages. */
  827.  
  828.         while(RexxMsg = (struct RexxMsg *)GetMsg(RexxPort))
  829.         {
  830.             if(RexxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
  831.                 FreeVecPooled(RexxMsg);
  832.             else
  833.                 ReplyRexxCommand(RexxMsg,-1,0);
  834.         }
  835.  
  836.         DeleteMsgPort(RexxPort);
  837.  
  838.         RexxPort = NULL;
  839.     }
  840.  
  841.     Forbid();
  842.  
  843.     RexxProcess = NULL;
  844.  
  845.     Signal((struct Task *)ThisProcess,SIG_HANDSHAKE);
  846. }
  847.  
  848.     /* HandleRexxJob(JobNode *UnusedJob):
  849.      *
  850.      *    Tiny & simple subroutine to read and examine all
  851.      *    messages coming in to be processed synchronously
  852.      *    by the `term' main process.
  853.      */
  854.  
  855. BOOL
  856. HandleRexxJob(JobNode *UnusedJob)
  857. {
  858.     struct RexxPkt *Packet;
  859.  
  860.         /* Obtain the message packet. */
  861.  
  862.     if(Packet = (struct RexxPkt *)GetMsg(TermRexxPort))
  863.     {
  864.         STRPTR Result;
  865.  
  866.         InRexx = TRUE;
  867.  
  868.         UpdateRequired = TransferUpdateRequired = FALSE;
  869.  
  870.             /* Execute the command. */
  871.  
  872.         PushStatus(STATUS_AREXX);
  873.         Result = (*Packet->CommandInfo->Routine)(Packet);
  874.         PopStatus();
  875.  
  876.             /* Free the packet data. */
  877.  
  878.         RexxPktCleanup(Packet,Result);
  879.  
  880.             /* Update the configuration if necessary. */
  881.  
  882.         if(UpdateRequired)
  883.             ConfigSetup();
  884.  
  885.             /* Update the XPR options if necessary. */
  886.  
  887.         if(TransferUpdateRequired)
  888.         {
  889.             if(ProtocolSetup(TRUE))
  890.                 SaveProtocolOpts();
  891.         }
  892.  
  893.             /* Return the message packet. */
  894.  
  895.         ReplyMsg((struct Message *)Packet);
  896.  
  897.         InRexx = FALSE;
  898.  
  899.         return(TRUE);
  900.     }
  901.     else
  902.         return(FALSE);
  903. }
  904.